<?php
/**
 * 易优CMS
 * ============================================================================
 * 版权所有 2016-2028 海口快推科技有限公司，并保留所有权利。
 * 网站地址: http://www.eyoucms.com
 * ----------------------------------------------------------------------------
 * 如果商业用途务必到官方购买正版授权, 以免引起不必要的法律纠纷.
 * ============================================================================
 * Author: 小虎哥 <1105415366@qq.com>
 * Date: 2018-4-3
 */

namespace app\common\model;

use think\Db;
use think\Model;
use app\common\logic\ClassifyLogic;

/**
 * 分类模型
 */
class Classify extends Model
{
    public $paramArr = [];

    // 初始化
    protected function initialize()
    {
        parent::initialize();
        $this->times = getTime();
        $this->dirname = 'ey_classify_';
        $this->paramArr = input('param.');
        $this->classify_db = Db::name('classify');
        $this->classifyLogic = new ClassifyLogic;
        $this->adminID = session('admin_info.admin_id');
    }

    // 新增分类
    public function insertClassify()
    {
        if (!empty($this->paramArr['id'])) $this->paramArr['level']++;
        if (!empty($this->paramArr['id']) && empty($this->paramArr['topid'])) $this->paramArr['topid'] = $this->paramArr['id'];
        $insert = [
            'channeltype' => 1,
            'current_channel' => 1,
            'parent_id' => intval($this->paramArr['id']),
            'topid' => intval($this->paramArr['topid']),
            'typename' => '',
            'grade' => intval($this->paramArr['level']),
            'templist' => 'lists_article.htm',
            'tempview' => 'view_article.htm',
            'sort_order' => 100,
            'is_hidden' => 1,
            'admin_id' => intval($this->adminID),
            'table' => 'article',
            'add_time' => $this->times,
            'update_time' => $this->times
        ];
        // 获取栏目空闲ID作为本次添加ID
        $idleID = $this->getClassifyIdleID();
        if (!empty($idleID)) $insert = array_merge(['id'=>$idleID], $insert);
        // dump($insert);exit;
        $insertID = $this->classify_db->insertGetId($insert);
        if (!empty($insertID)) {
            \think\Cache::clear("classify");
            // 删除多余数据
            $this->delRedundantData($insertID);
            // 同步栏目ID到权限组，默认是赋予该栏目的权限
            model('AuthRole')->syn_auth_role($insertID);
            // 更新目录英文名、目录存放HTML路径、列表静态文件存放规则
            $update = [
                'dirname' => $this->dirname . $insertID,
                'dirpath' => $this->paramArr['dirpath'] . '/' . $this->dirname . $insertID,
                'update_time' => $this->times
            ];
            $this->classify_db->where(['id' => intval($insertID)])->update($update);
            // 返回结束
            return intval($insertID);
        }
        return false;
    }

    // 更新分类
    public function updateClassify()
    {
        if (empty($this->paramArr['id'])) return false;
        $where = [
            'id' => $this->paramArr['id']
        ];
        $update = [
            $this->paramArr['field'] => $this->paramArr['value'],
            'update_time' => $this->times,
        ];
        // 如果是更新分类名称则执行
        if ('typename' == $this->paramArr['field']) {
            $classify = $this->classify_db->where($where)->field('id, dirname, dirpath, is_hidden')->find();
            if (1 === intval($classify['is_hidden']) && preg_match("/$this->dirname/", $classify['dirname'])) {
                $dirname = $this->classifyLogic->get_dirname($this->paramArr['value']);
                $update['dirname'] = $dirname;
                $update['dirpath'] = str_replace($this->dirname . $this->paramArr['id'], $dirname, $classify['dirpath']);
                $update['is_hidden'] = 0;
            }
        }
        // dump($update);exit;
        $updateID = $this->classify_db->where($where)->update($update);
        if (!empty($updateID)) {
            \think\Cache::clear("classify");
            // 返回结束
            return true;
        }
        return false;
    }

    // 删除分类
    public function deleteClassify($clear = false)
    {
        $where = [];
        if (!empty($clear)) {
            $where = [
                'typename' => '',
                'is_hidden' => 1,
                'admin_id' => intval($this->adminID)
            ];
        }
        else if (!empty($this->paramArr['id'])) {
            $where = [
                'id' => $this->paramArr['id']
            ];
        }
        return !empty($where) ? $this->classify_db->where($where)->delete(true) : false;
    }

    // 获取分类空闲ID，用于栏目ID占位
    public function getClassifyIdleID($returnArr = false)
    {
        $classifyArr = $this->classify_db->field('id')->order('id asc')->getAllWithIndex('id');
        if (!empty($classifyArr)) {
            $endArr = end($classifyArr);
            $maxID = $endArr['id'];
            $result = [];
            for ($i = 1; $i <= $maxID; $i++) {
                if (!isset($classifyArr[$i])) {
                    array_push($result, $i);
                    if (empty($returnArr)) break;
                }
            }
            if (empty($returnArr)) {
                return $result[0];
            } else {
                return $result;
            }
        } else {
            return false;
        }
    }

    // 新增栏目时删除多余数据，用于栏目ID占位
    public function delRedundantData($typeid = 0)
    {
        Db::name('channelfield_bind')->where(['typeid'=>$typeid])->delete(true);
    }

    /**
     * 获取单条记录
     * @author wengxianhu by 2017-7-26
     */
    public function getInfo($id, $field = '', $get_parent = false)
    {
        if (empty($field)) {
            $field = 'a.*';
        }
        $field .= ', a.id as typeid';

        /*当前栏目信息*/
        $result = $this->classify_db->field($field)
            ->alias('a')
            ->where('a.id', $id)
            ->cache(true,EYOUCMS_CACHE_TIME,"classify")
            ->find();
        /*--end*/
        if (!empty($result)) {
            if ($get_parent) {
                $result['typeurl'] = $this->getTypeUrl($result); // 当前栏目的URL
                /*获取当前栏目父级栏目信息*/
                if ($result['parent_id'] > 0) {
                    $parent_row = $this->classify_db->field($field)
                        ->alias('a')
                        ->where('a.id', $result['parent_id'])
                        ->cache(true,EYOUCMS_CACHE_TIME,"classify")
                        ->find();
                    $ptypeurl = $this->getTypeUrl($parent_row);
                    $parent_row['typeurl'] = $ptypeurl;
                } else {
                    $parent_row = $result;
                }
                /*--end*/

                /*给每个父类字段开头加上p*/
                foreach ($parent_row as $key => $val) {
                    $newK = 'p'.$key;
                    $parent_row[$newK] = $val;
                }
                /*--end*/
                $result = array_merge($result, $parent_row);
            } else {
                $result = $this->parentAndTopInfo($id, $result);
            }
        }

        return $result;
    }

    /**
     * 获取指定栏目的父级和顶级栏目信息（用于前台与静态生成）
     * @author wengxianhu by 2017-7-26
     */
    public function parentAndTopInfo($id, $result = [])
    {
        $result['typeurl'] = $this->getTypeUrl($result); // 当前栏目的URL
        if (!empty($result['parent_id'])) {
            // 当前栏目的父级栏目信息
            $parent_row = $this->classify_db->where('id', $result['parent_id'])
                ->cache(true,EYOUCMS_CACHE_TIME,"classify")
                ->find();
            $ptypeid = $parent_row['id'];
            $ptypeurl = $this->getTypeUrl($parent_row);
            $ptypename = $parent_row['typename'];
            $pdirname = $parent_row['dirname'];
            // 当前栏目的顶级栏目信息
            if (!isset($result['toptypeurl'])) {
                $allPid = $this->getAllPid($id);
                $toptypeinfo = current($allPid);
                $toptypeid = $toptypeinfo['id'];
                $toptypeurl = $this->getTypeUrl($toptypeinfo);
                $toptypename = $toptypeinfo['typename'];
                $topdirname = $toptypeinfo['dirname'];
            }
            // end
        } else {
            // 当前栏目的父级栏目信息 或 顶级栏目的信息
            $toptypeid = $ptypeid = $result['id'];
            $toptypeurl = $ptypeurl = $result['typeurl'];
            $toptypename = $ptypename = $result['typename'];
            $topdirname = $pdirname = $result['dirname'];
        }
        // 当前栏目的父级栏目信息
        $result['ptypeid'] = $ptypeid;
        $result['ptypeurl'] = $ptypeurl;
        $result['ptypename'] = $ptypename;
        $result['pdirname'] = $pdirname;
        // 当前栏目的顶级栏目信息
        !isset($result['toptypeid']) && $result['toptypeid'] = $toptypeid;
        !isset($result['toptypeurl']) && $result['toptypeurl'] = $toptypeurl;
        !isset($result['toptypename']) && $result['toptypename'] = $toptypename;
        !isset($result['topdirname']) && $result['topdirname'] = $topdirname;
        // end

        return $result;
    }

    /**
     * 根据目录名称获取单条记录
     * @author wengxianhu by 2018-4-20
     */
    public function getInfoByDirname($dirname)
    {
        $cacheKey = 'classify-'.md5(__CLASS__.__FUNCTION__.$dirname);
        $result = cache($cacheKey);
        if (empty($result)) {
            $result = $this->classify_db->field('a.*, a.id as typeid')
                ->alias('a')
                ->where('a.dirname', $dirname)
                ->find();
            if (!empty($result)) {
                $result['typeurl'] = $this->getTypeUrl($result);

                $result_tmp = $this->classify_db->where('id', $result['parent_id'])->find();
                $result['ptypeurl'] = $this->getTypeUrl($result_tmp);
            }

            cache($cacheKey, $result, null, 'classify');
        }

        return $result;
    }

    /**
     * 检测是否有子栏目
     * @author wengxianhu by 2017-7-26
     */
    public function hasChildren($id)
    {
        if (is_array($id)) {
            $ids = array_unique($id);
            $row = $this->classify_db->field('parent_id, count(id) AS total')->where([
                    'parent_id'=>['IN', $ids],
                    'is_del'    => 0,
                ])->group('parent_id')->getAllWithIndex('parent_id');
            return $row;
        } else {
            $count = $this->classify_db->where([
                    'parent_id' => $id,
                    'is_del'    => 0,
                ])->count('id');
            return ($count > 0 ? 1 : 0);
        }
    }

    /**
     * 获取栏目的URL
     */
    public function getTypeUrl($res)
    {
        $typeurl = typeurl("home/Lists/index", $res);

        return $typeurl;
    }


    /**
     * 获取指定级别的栏目列表
     * @param string type son表示下一级栏目,self表示同级栏目,top顶级栏目
     * @param boolean $self 包括自己本身
     * @author wengxianhu by 2018-4-26
     */
    public function getChannelList($id = '', $type = 'son')
    {
        $result = array();
        switch ($type) {
            case 'son':
                $result = $this->getSon($id, false);
                break;

            case 'self':
                $result = $this->getSelf($id);
                break;

            case 'top':
                $result = $this->getTop();
                break;

            case 'sonself':
                $result = $this->getSon($id, true);
                break;
        }

        return $result;
    }

    /**
     * 获取下一级栏目
     * @param string $self true表示没有子栏目时，获取同级栏目
     * @author wengxianhu by 2017-7-26
     */
    public function getSon($id, $self = false)
    {
        $result = array();
        if (empty($id)) {
            return $result;
        }

        $arctype_max_level = intval(config('global.arctype_max_level'));
        $map = array(
            'is_hidden'   => 0,
            'status'  => 1,
            'is_del'  => 0, // 回收站功能
        );
        $res = $this->classifyLogic->arctype_list($id, 0, false, $arctype_max_level, $map);

        if (!empty($res)) {
            $arr = group_same_key($res, 'parent_id');
            for ($i=0; $i < $arctype_max_level; $i++) {
                foreach ($arr as $key => $val) {
                    foreach ($arr[$key] as $key2 => $val2) {
                        if (!isset($arr[$val2['id']])) continue;
                        $val2['children'] = $arr[$val2['id']];
                        $arr[$key][$key2] = $val2;
                    }
                }
            }
            if (isset($arr[$id])) {
                $result = $arr[$id];
            }
        }

        if (empty($result) && $self == true) {
            $result = $this->getSelf($id);
        }

        return $result;
    }

    /**
     * 获取同级栏目
     * @author wengxianhu by 2017-7-26
     */
    public function getSelf($id)
    {
        $result = array();
        if (empty($id)) {
            return $result;
        }

        $map = array(
            'id'   => $id,
            'is_hidden'   => 0,
            'status'  => 1,
            'is_del'  => 0, // 回收站功能
        );
        $res = $this->classify_db->field('parent_id')->where($map)->find();

        if ($res) {
            $newId = $res['parent_id'];
            $arctype_max_level = intval(config('global.arctype_max_level'));
            $map = array(
                'is_hidden'   => 0,
                'status'  => 1,
            );
            $res = $this->classifyLogic->arctype_list($newId, 0, false, $arctype_max_level, $map);

            if (!empty($res)) {
                $arr = group_same_key($res, 'parent_id');
                for ($i=0; $i < $arctype_max_level; $i++) {
                    foreach ($arr as $key => $val) {
                        foreach ($arr[$key] as $key2 => $val2) {
                            if (!isset($arr[$val2['id']])) continue;
                            $val2['children'] = $arr[$val2['id']];
                            $arr[$key][$key2] = $val2;
                        }
                    }
                }
                $result = $arr[$newId];
            }
        }

        return $result;
    }

    /**
     * 获取顶级栏目
     * @author wengxianhu by 2017-7-26
     */
    public function getTop()
    {
        $arctype_max_level = intval(config('global.arctype_max_level'));
        $map = array(
            'is_hidden'   => 0,
            'status'  => 1,
            'is_del'  => 0, // 回收站功能
        );
        $res = $this->classifyLogic->arctype_list(0, 0, false, $arctype_max_level, $map);

        $result = array();
        if (!empty($res)) {
            $arr = group_same_key($res, 'parent_id');
            for ($i=0; $i < $arctype_max_level; $i++) {
                foreach ($arr as $key => $val) {
                    foreach ($arr[$key] as $key2 => $val2) {
                        if (!isset($arr[$val2['id']])) continue;
                        $val2['children'] = $arr[$val2['id']];
                        $arr[$key][$key2] = $val2;
                    }
                }
            }
            reset($arr);
            $firstResult = current($arr);
            $result = $firstResult;
        }

        return $result;
    }

    /**
     * 获取当前栏目及所有子栏目
     * @param boolean $self 包括自己本身
     * @author wengxianhu by 2017-7-26
     */
    public function getHasChildren($id, $self = true)
    {
        $args = [$id, $self];
        $cacheKey = 'classify-'.md5(__CLASS__.__FUNCTION__.json_encode($args));
        $result = cache($cacheKey);
        if (empty($result)) {
            static $res = null;
            if (null === $res) {
                $childrenRow = $this->classify_db->field('parent_id, count(id) as has_children')
                    ->where([
                        'status'  => 1,
                        'is_del'  => 0,
                    ])->group('parent_id')
                    ->getAllWithIndex('parent_id');

                $where = [
                    'status'  => 1,
                    'is_del'  => 0,
                ];
                $res = $this->classify_db->where($where)->order('parent_id asc, sort_order asc, id asc')->select();
                foreach ($res as $key => $val) {
                    $val['has_children'] = !empty($childrenRow[$val['id']]) ? $childrenRow[$val['id']]['has_children'] : 0;
                    $res[$key] = $val;
                }
            }

            $result = arctype_options($id, $res, 'id', 'parent_id');

            if (!$self) {
                array_shift($result);
            }

            cache($cacheKey, $result, null, "classify");
        }

        return $result;
    }

    /**
     * 获取所有栏目
     * @param   int     $id     栏目的ID
     * @param   int     $selected   当前选中栏目的ID
     * @param   int     $channeltype      查询条件
     * @author wengxianhu by 2017-7-26
     */
    public function getList($id = 0, $select = 0, $re_type = true, $map = array())
    {
        $id = $id ? intval($id) : 0;
        $select = $select ? intval($select) : 0;

        $arctype_max_level = intval(config('global.arctype_max_level'));
        $options = $this->classifyLogic->arctype_list($id, $select, $re_type, $arctype_max_level, $map);

        return $options;
    }


    /**
     * 默认获取全部
     * @author 小虎哥 by 2018-4-16
     */
    public function getAll($field = '*', $map = array(), $index_key = '')
    {
        $args = [$field, $map, $index_key];
        $cacheKey = 'classify-'.md5(__CLASS__.__FUNCTION__.json_encode($args));
        $result = cache($cacheKey);
        if (empty($result)) {
            $result = $this->classify_db->field($field)
                ->where($map)
                ->order('sort_order asc')
                // ->cache(true,EYOUCMS_CACHE_TIME,"classify")
                ->select();

            if (!empty($index_key)) {
                $result = convert_arr_key($result, $index_key);
            }

            cache($cacheKey, $result, null, "classify");
        }

        return $result;
    }

    /**
     * 获取当前栏目的所有父级
     * @author wengxianhu by 2018-4-26
     */
    public function getAllPid($id, $is_RecycleBin = false)
    {
        $args = [THEME_STYLE, $id, $is_RecycleBin, request()->baseFile()];
        $cacheKey = 'classify-'.md5(__CLASS__.__FUNCTION__.json_encode($args));
        $data = cache($cacheKey);
        if (empty($data)) {
            $data = array();
            $typeid = $id;
            $map = [
                'status'    => 1,
            ];
            if (false === $is_RecycleBin) $map['is_del'] = 0;
            $classify_list = $this->classify_db->field('*, id as typeid')
                ->where($map)
                ->getAllWithIndex('id');
            if (isset($classify_list[$typeid])) {
                // 第一个先装起来
                $classify_list[$typeid]['typeurl'] = $this->getTypeUrl($classify_list[$typeid]);
                $data[$typeid] = $classify_list[$typeid];
            } else {
                return $data;
            }

            while (true)
            {
                $typeid = $classify_list[$typeid]['parent_id'];
                if($typeid > 0 && $id != $typeid){
                    if (isset($classify_list[$typeid])) {
                        $classify_list[$typeid]['typeurl'] = $this->getTypeUrl($classify_list[$typeid]);
                        $data[$typeid] = $classify_list[$typeid];
                    }
                } else {
                    break;
                }
            }
            $data = array_reverse($data, true);

            cache($cacheKey, $data, null, "classify");
        }

        return $data;
    }

    /**
     * 获取多个栏目的所有父级
     * @author wengxianhu by 2018-4-26
     */
    public function getAllPidByids($ids = [])
    {
        $data = array();
        $classify_list = $this->getAll('id,parent_id', [], 'id');
        foreach ($ids as $key => $typeid) {
            if (isset($classify_list[$typeid])) {
                // 第一个先装起来
                $data[$typeid] = $classify_list[$typeid];
            }

            while (true)
            {
                $typeid = $classify_list[$typeid]['parent_id'];
                if($typeid > 0){
                    if (isset($classify_list[$typeid])) {
                        $data[$typeid] = $classify_list[$typeid];
                    }
                } else {
                    break;
                }
            }
        }

        !empty($data) && $data = array_reverse($data, true);

        return $data;
    }

    /**
     * 伪删除指定栏目（包括子栏目、所有相关文档）
     */
    public function pseudo_del($typeid)
    {
        $childrenList = $this->getHasChildren($typeid); // 获取当前栏目以及所有子栏目
        $typeidArr = get_arr_column($childrenList, 'id'); // 获取栏目数组里的所有栏目ID作为新的数组
        $typeidArr2 = $typeidArr;

        /*标记当前栏目以及子栏目为被动伪删除*/
        $sta1 = $this->classify_db
            ->where([
                'id'    => ['IN', $typeidArr],
                'is_del'    => 0,
                'del_method' => 0,
            ])
            ->cache(true,null,"classify")
            ->update([
                'is_del'    => 1,
                'del_method'    => 2, // 1为主动删除，2为跟随上级栏目被动删除
                'update_time'   => getTime(),
            ]); // 伪删除栏目
        /*--end*/

        if ($sta1 !== false) {
            model('Archives')->pseudo_del($typeidArr); // 删除文档
            return true;
        }

        return false;
    }

    /**
     * 删除指定栏目（包括子栏目、所有相关文档）
     */
    public function del($typeid)
    {
        $childrenList = $this->getHasChildren($typeid); // 获取当前栏目以及所有子栏目
        $typeidArr = get_arr_column($childrenList, 'id'); // 获取栏目数组里的所有栏目ID作为新的数组

        $sta = $this->classify_db
            ->where([
                'id'    => ['IN', $typeidArr],
            ])
            ->cache(true,null,"classify")
            ->delete(); // 删除栏目
        if ($sta !== false) {
            model('Archives')->del($typeidArr); // 删除文档
            \think\Cache::clear('taglist');
            \think\Cache::clear('archives');
            \think\Cache::clear('classify');

            return true;
        }

        return false;
    }

    /**
     * 每个栏目的顶级栏目的目录名称
     */
    public function getEveryTopDirnameList()
    {
        $cacheKey = 'classify-'.md5(__CLASS__.__FUNCTION__);
        $result = cache($cacheKey);
        if (empty($result)) {
            $fields = "c.id, c.parent_id, c.dirname, c.grade, count(s.id) as has_children";
            $row = $this->classify_db
                ->field($fields)
                ->alias('c')
                ->join('__classify__ s','s.parent_id = c.id','LEFT')
                ->group('c.id')
                ->order('c.parent_id asc, c.sort_order asc, c.id')
                // ->cache(true,EYOUCMS_CACHE_TIME,"classify")
                ->select();
            $row = arctype_options(0, $row, 'id', 'parent_id');

            $result = array();
            foreach ($row as $key => $val) {
                if (empty($val['parent_id'])) {
                    $val['tdirname'] = $val['dirname'];
                } else {
                    $val['tdirname'] = isset($row[$val['parent_id']]['tdirname']) ? $row[$val['parent_id']]['tdirname'] : $val['dirname'];
                }
                $row[$key] = $val;
                $result[md5($val['dirname'])] = $val;
            }

            cache($cacheKey, $result, null, "classify");
        }

        return $result;
    }

    /**
     * 获取当前栏目下有几层，包括自身这一层
     * @author wengxianhu by 2017-7-26
     */
    public function getHierarchy($id = '')
    {
        $hierarchy = 1;
        $ids = [$id];
        while (true)
        {
            $ids = $this->classify_db->where([
                    'parent_id'    => ['IN', $ids],
                ])->column('id');
            if (empty($ids)) {
                break;
            } else {
                $hierarchy++;
            }
        }

        return $hierarchy;
    }

    public function getArcTypeIdleID($returnArr = false)
    {
        $classifyArr = $this->classify_db->field('id')->order('id asc')->getAllWithIndex('id');
        if (!empty($classifyArr)) {
            $endArr = end($classifyArr);
            $maxID = $endArr['id'];
            $result = [];
            for ($i = 1; $i <= $maxID; $i++) {
                if (!isset($classifyArr[$i])) {
                    array_push($result, $i);
                    if (empty($returnArr)) break;
                }
            }
            if (empty($returnArr)) {
                return $result[0];
            } else {
                return $result;
            }
        } else {
            return false;
        }
    }
}